#!/usr/bin/python
#coding=utf8

# JS Make 工具
# 用于编译打包JS
# make.py make -t tag 编译文件到../out/tag 不使用-t 使用dev目录
# make.py clean 清除../out目录

import sys, os, getopt, re, shutil

#Packge define begin
ERR_OPTS    = 1
ERR_ACTION  = 2

EVN_VARS    = {
    "PROJECT_PATH"  : os.getcwd()
}

DEFALUT_CONF= {
    "SHOW_MORE" : True,
    "OUT_PATH"  : os.path.join(EVN_VARS["PROJECT_PATH"], "../out/"),
    "BUILD_TAG" : "dev",
    "CACHE_REG" : re.compile("^[^_].*(js|css)$"),
    "INC_MARK"  : [
        re.compile("^.*//inc\s*(.+)$", re.M),
        re.compile("^.*/\*inc\s*(.+)\*/$", re.M)
    ]
}
#Packge define end

class Maker():
    
    # Method unIncMark
    # 用于展开Inc标记
    # param filePath 目标文件地址
    # param basePath 基址，默认根据filePath自动寻找
    def unIncMark(self, filePath, basePath = False):
        if not basePath:
            basePath = os.path.dirname(filePath)

        fh      = open(filePath, 'r')
        content = fh.read()

        def handler(match):
            incFileName = match.group(1)
            realPath    = os.path.join(basePath, incFileName)
            return self.unIncMark(realPath)

        for _, reg in enumerate(DEFALUT_CONF["INC_MARK"]):
             content = reg.sub(handler, content)
        
        return content

    # Method Action Make
    # 用于编译整个项目
    # param tag 编译出来的buildTag 默认为 DEFALUT_CONF -> BUILD_TAG
    # param projectPath 项目目录，默认为 EVN_VARS -> PROJECT_PATH
    # param outPath 输出目录 默认为 DEFALUT_CONF -> OUT_PATH
    def make(self, tag = DEFALUT_CONF["BUILD_TAG"], projectPath = EVN_VARS["PROJECT_PATH"], outPath = DEFALUT_CONF["OUT_PATH"]): 
        
        outPath     = os.path.join(outPath, tag)

        if os.path.exists(outPath):
            shutil.rmtree(outPath)

        makedDict   = {}
        makedList   = []
        whileStack  = []
        def walk(path):
            ls      = os.listdir(path)
            for idx, fileName in enumerate(ls):
                filePath = path + "/" + fileName 
                if os.path.isdir(filePath):
                    whileStack.append(fileName)
                    walk(filePath)
                elif os.path.isfile(filePath):
                    if DEFALUT_CONF["CACHE_REG"].match(fileName):
                        dirname = os.path.join("/".join(whileStack))
                        makedList.append((os.path.join(dirname ,fileName), dirname))
            if len(whileStack):
                whileStack.pop()

        walk(projectPath)

        dirList = []
        for idx, (filePath, dirname) in enumerate(makedList):
            realPath = os.path.join(projectPath, filePath)
            makedDict[filePath] = self.unIncMark(realPath)
            dirList.append(dirname)
        
        for idx, dirname in enumerate({}.fromkeys(dirList).keys()):
            dirPath = os.path.join(outPath, dirname)
            #若无输出目录
            if not os.path.exists(dirPath):
                os.makedirs(dirPath)
        
        for filePath in makedDict:
            realPath = os.path.join(outPath, filePath)
            fh = open(realPath, 'w')
            fh.write(makedDict[filePath])
            fh.close()

    # Method clean
    # 用于清理输出目录
    # param outPath 输出目录 默认为 DEFALUT_CONF -> OUT_PATH
    def clean(self, outPath = DEFALUT_CONF["OUT_PATH"]):
        if os.path.exists(outPath):
            shutil.rmtree(outPath)





#####################################################If main module

if __name__ == "__main__":

    myArgs      = sys.argv[1:]

    if not len(myArgs):
        print "Not Action."
        exit(ERR_OPTS)

    actionName  = myArgs[0]
    opts, args  = getopt.getopt(myArgs[1:], "t:")
    optsDict    = {}

    if len(opts):
        optsDict= dict(opts)
    
    maker       = Maker()

    if actionName == "make" :
        maker.make(optsDict.get("-t") or DEFALUT_CONF["BUILD_TAG"])
    elif actionName == "clean" :
        maker.clean()
    else:
        print "Action not found."
        exit(ERR_ACTION)
    
